package edu.ucsd.cse110;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.TextView;
import edu.ucsd.cse110.model.Log;

/**
 * Displays a month view.
 */
public class MonthViewFragment extends Fragment {
	/**
	 * TODO: Need documentation.
	 */
	private class MyArrayAdapter extends ArrayAdapter<String> {
		private List<String> availableDays;
		private List<String> list;
		private Context mContext;

		public MyArrayAdapter(Context context, List<String> objects,
				List<String> availableDays) {
			super(context, R.layout.calendar_item, objects);
			mContext = context;
			list = objects;
			this.availableDays = availableDays;
		}

		/**
		 * TODO: Need documentation.
		 */
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {

			LayoutInflater inflater = (LayoutInflater) mContext
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			View view = inflater.inflate(R.layout.calendar_item, parent, false);

			// Shows the details of the WOD when the item is pressed.

			// Sets the name of the WOD
			TextView txtName = (TextView) view.findViewById(R.id.day);
			txtName.setText(list.get(position));

			TextView colorBar = (TextView) view.findViewById(R.id.day_color);

			if (availableDays.contains(calendarStrings.get(position))) {
				colorBar.setBackgroundColor(0xffffa500);// Orange
			}

			int currentDay = Calendar.getInstance().get(Calendar.DATE);
			if (calendarStrings.get(position).equals(
					Integer.toString(currentDay))
					&& (Calendar.getInstance().get(Calendar.MONTH) == (currentDate
							.get(Calendar.MONTH)))
					&& (Calendar.getInstance().get(Calendar.YEAR) == (currentDate
							.get(Calendar.YEAR)))) {
				colorBar.setBackgroundColor(0xff0000ff);// Blue
			}
			return view;
		}

	}

	private List<String> calendarStrings;
	private Calendar currentDate;
	private final int REQUEST_CODE_MULTIPLE_DATE_SELECTION = 1;
	private View view;

	/**
	 * Initializes local variables.
	 */
	public MonthViewFragment() {
		currentDate = Calendar.getInstance();
	}

	/**
	 * Creates a new logbook entry at a specific date.
	 * 
	 * @param c
	 *            The date of the new logbook entry.
	 */
	private void createNewLogbookEntry(Calendar c) {
		Intent i = new Intent();
		i.putExtra("year", c.get(Calendar.YEAR));
		i.putExtra("month", c.get(Calendar.MONTH));
		i.putExtra("day", c.get(Calendar.DATE));
		getActivity().setResult(2, i);
		getActivity().finish();
	}

	/**
	 * Gets the number of days in the current month.
	 * 
	 * @return Number of days in the current month.
	 */
	private int daysInMonth() {
		int year = currentDate.get(Calendar.YEAR);
		int month = currentDate.get(Calendar.MONTH);
		Calendar cal = Calendar.getInstance();
		cal.clear();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month);
		return cal.getActualMaximum(Calendar.DAY_OF_MONTH);

	}

	/**
	 * Renders calendar on the screen.
	 */
	public void drawCalendar() {
		GridView gridview = (GridView) view.findViewById(R.id.calendar);
		calendarStrings = getStrings();

		// Gets the dates of all log entries.
		LocalDatabaseManager database = new LocalDatabaseManager(getActivity());
		final List<Log> days = database.getAllLog();
		database.close();

		ArrayList<Calendar> blah = new ArrayList<Calendar>();
		for (int i = 0; i < days.size(); i++) {
			blah.add(days.get(i).getDate());
		}

		// Sets up the days of the month.
		final ArrayList<String> availableDays = handleMonthAndYears(blah);
		gridview.setAdapter(new MyArrayAdapter(getActivity(), calendarStrings,
				availableDays));
		gridview.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View v,
					int position, long id) {
				Calendar calCompare = Calendar.getInstance();
				calCompare.clear();
				calCompare.set(Calendar.YEAR,
						Calendar.getInstance().get(Calendar.YEAR));
				calCompare.set(Calendar.MONTH,
						Calendar.getInstance().get(Calendar.MONTH));
				calCompare.set(Calendar.DATE,
						Calendar.getInstance().get(Calendar.DATE));

				Calendar c = Calendar.getInstance();
				c.clear();
				c.set(Calendar.YEAR, currentDate.get(Calendar.YEAR));
				c.set(Calendar.MONTH, currentDate.get(Calendar.MONTH));

				try {
					c.set(Calendar.DATE,
							Integer.parseInt(calendarStrings.get(position)));
				} catch (NumberFormatException e) {
					return;
				}

				if (c.getTimeInMillis() <= calCompare.getTimeInMillis()) {
					List<Log> list = new ArrayList<Log>();
					LocalDatabaseManager db = new LocalDatabaseManager(
							getActivity());
					list = db.getLog(
							String.format("%s = ?", Log.COLUMNS[1]),
							new String[] { Long.toString(c.getTimeInMillis()) },
							null, null, null);
					db.close();

					// Opens or creates a log entry.
					if (list.size() > 1) {
						Intent i = new Intent(getActivity(),
								MultipleLogActivity.class);
						i.putExtra("year", c.get(Calendar.YEAR));
						i.putExtra("month", c.get(Calendar.MONTH));
						i.putExtra("day", c.get(Calendar.DATE));
						startActivityForResult(i,
								REQUEST_CODE_MULTIPLE_DATE_SELECTION);
					} else if (list.size() == 1) {
						openLogbookEntry(list.get(0).getId());
					} else {
						createNewLogbookEntry(c);
					}
				}
			}
		});

		// Sets the month and date.
		TextView monthText = (TextView) view.findViewById(R.id.month);
		TextView yearText = (TextView) view.findViewById(R.id.year);

		monthText.setText(Utility.calendarToString(currentDate, "MMMM"));
		yearText.setText(Utility.calendarToString(currentDate, "yyyy"));

	}

	/**
	 * Gets current date.
	 * 
	 * @return Current date.
	 */
	public Calendar getCurrentDate() {
		return currentDate;
	}

	/**
	 * Gets the first day of the month.
	 * 
	 * @return The first day of the month.
	 */
	private int getFirstDayOfMonth() {
		int year = currentDate.get(Calendar.YEAR);
		int month = currentDate.get(Calendar.MONTH);
		Calendar cal = Calendar.getInstance();
		cal.clear();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month);
		return cal.get(Calendar.DAY_OF_WEEK);
	}

	/**
	 * TODO: Need documentation.
	 */
	private List<String> getStrings() {
		List<String> stringArray = new ArrayList<String>();
		int k = 1;

		for (int i = 0; i < (getFirstDayOfMonth() - 1); i++) {
			stringArray.add("");
		}

		for (int i = getFirstDayOfMonth() - 1; i < ((daysInMonth() + getFirstDayOfMonth()) - 1); i++) {
			stringArray.add(Integer.toString(k));
			k++;
		}

		for (int i = (daysInMonth() + getFirstDayOfMonth()) - 1; i < stringArray
				.size(); i++) {
			stringArray.add("");
		}

		return stringArray;
	}

	/**
	 * TODO: Need documentation.
	 */
	private ArrayList<String> handleMonthAndYears(ArrayList<Calendar> dates) {
		ArrayList<String> result = new ArrayList<String>();

		int currentMonth = currentDate.get(Calendar.MONTH);
		int currentYear = currentDate.get(Calendar.YEAR);

		for (Calendar i : dates) {
			if (i == null) {
				continue;
			}
			int month = i.get(Calendar.MONTH);
			int year = i.get(Calendar.YEAR);

			if ((month == currentMonth) && (year == currentYear)) {
				result.add("" + i.get(Calendar.DAY_OF_MONTH));
			}
		}

		return result;
	}

	/**
	 * Rolls to the next month.
	 */
	public void nextMonth() {
		if (currentDate != null) {
			if (currentDate.get(Calendar.MONTH) == Calendar.DECEMBER) {
				currentDate.roll(Calendar.YEAR, true);
			}
			currentDate.roll(Calendar.MONTH, true);
		}
	}

	/**
	 * TODO: Need documentation.
	 */
	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		switch (requestCode) {
		case REQUEST_CODE_MULTIPLE_DATE_SELECTION:
			if (resultCode == Activity.RESULT_OK) {
				openLogbookEntry(data.getExtras().getInt("id"));
			}
			break;
		}
	}

	/**
	 * TODO: Need documentation.
	 */
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		view = inflater.inflate(R.layout.calendar, container, false);
		getActivity().setRequestedOrientation(
				ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		drawCalendar();

		return view;
	}

	/**
	 * Opens the logbook entry with the specified id.
	 */
	private void openLogbookEntry(int id) {
		Intent i = new Intent();
		i.putExtra("id", id);
		getActivity().setResult(1, i);
		getActivity().finish();
	}

	/**
	 * Rolls back to the previous month.
	 */
	public void prevMonth() {
		if (currentDate != null) {
			if (currentDate.get(Calendar.MONTH) == Calendar.JANUARY) {
				currentDate.roll(Calendar.YEAR, false);
			}
			currentDate.roll(Calendar.MONTH, false);
		}
	}
}